﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Data;
using System.Reflection;
using System.Linq.Expressions;
using EntityFrameworks.Entity.Core;
using EntityFrameworks.Entity.Core.Specification;
using IRepository.Core;
namespace EntityFrameworks.Data.Core
{

    /// <summary>
    /// EF ORM 操作功能类
    /// 它不是抽象类，它在基础设施层会以基类或者功能对象的方式出现
    /// </summary>
    public class ObjectContextRepository<T> :
         IExtensionRepository<T> where T : class
    {
        protected ObjectContext Db { get; private set; }
        IUnitOfWork iUnitWork;
        public ObjectContextRepository(IUnitOfWork db)
        {
            iUnitWork = db;
            Db = (ObjectContext)db;
        }


        #region IRepository<T> 成员

        public void Insert(T item)
        {
            Db.CreateObjectSet<T>().AddObject(item);
            SaveChanges();
        }


        public void Delete(T item)
        {
            (item as IEntityWithKey).EntityKey = Db.CreateEntityKey(typeof(T).Name, item);
            Db.Attach((item as IEntityWithKey));
            Db.ObjectStateManager.ChangeObjectState(item, EntityState.Deleted);

            SaveChanges();
        }

        public void Update(T item)
        {
            (item as IEntityWithKey).EntityKey = Db.CreateEntityKey(typeof(T).Name, item);
            Db.Attach((item as IEntityWithKey));
            Db.ObjectStateManager.ChangeObjectState(item, EntityState.Deleted);

            SaveChanges();
        }

        public IQueryable<T> GetModel()
        {
            return Db.CreateObjectSet<T>();
        }
        #endregion

        #region IExtensionRepository<T> 成员

        public void Insert(IEnumerable<T> item)
        {
            item.ToList().ForEach(i => this.Insert(i));
        }

        public void Update(IEnumerable<T> item)
        {
            item.ToList().ForEach(i => this.Update(i));
        }

        public void Delete(IEnumerable<T> item)
        {
            item.ToList().ForEach(i => this.Delete(i));
        }

        public T Find(params object[] id)
        {
            var count = 0;
            List<PropertyInfo> res_Primary = new List<PropertyInfo>();
            List<EntityKeyMember> keyMemberList = new List<EntityKeyMember>();
            PropertyInfo[] properties = typeof(T).GetProperties();
            foreach (PropertyInfo pI in properties)
            {
                System.Object[] attributes = pI.GetCustomAttributes(true);
                foreach (object attribute in attributes)
                {
                    if (attribute is EdmScalarPropertyAttribute)
                    {
                        if ((attribute as EdmScalarPropertyAttribute).EntityKeyProperty && !(attribute as EdmScalarPropertyAttribute).IsNullable)
                            keyMemberList.Add(new EntityKeyMember(pI.Name, id[count]));
                        count++;
                    }

                }
            }
            return Db.GetObjectByKey(new EntityKey(Db.DefaultContainerName + "." + typeof(T).Name, keyMemberList)) as T;
        }

        public void Update(Expression<Action<T>> entity)
        {
            throw new NotImplementedException();
        }

        public IQueryable<T> GetModel(ISpecification<T> specification)
        {
            return GetModel().Where(specification.SatisfiedBy());
        }

        #endregion

        #region Protected Methods
        /// <summary>
        /// 根据工作单元的IsNotSubmit的属性，去判断是否提交到数据库
        /// 一般地，在多个repository类型进行组合时，这个IsNotSubmit都会设为true，即不马上提交，
        /// 而对于单个repository操作来说，它的值不需要设置，使用默认的false，将直接提交到数据库，这也保证了操作的原子性。
        /// </summary>
        protected virtual void SaveChanges()
        {
            Db.SaveChanges();
        }
        #endregion

        #region IExtensionRepository<T> 成员

        public event Action<SavedEventArgs> AfterSaved;

        public event Action<SavedEventArgs> BeforeSaved;

        public IQueryable<T> GetModel(Expression<Func<T, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        public T Find(Expression<Func<T, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        public T Find(ISpecification<T> specification)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IExtensionRepository<T> 成员


        public void Update<T>(Expression<Action<T>> entity) where T : class
        {
            throw new NotImplementedException();
        }

        public void BulkInsert(IEnumerable<T> item, bool isRemoveIdentity)
        {
            throw new NotImplementedException();
        }

        public void BulkInsert(IEnumerable<T> item)
        {
            throw new NotImplementedException();
        }

        public void BulkUpdate(IEnumerable<T> item, params string[] fieldParams)
        {
            throw new NotImplementedException();
        }

        public void BulkDelete(IEnumerable<T> item)
        {
            throw new NotImplementedException();
        }

        #endregion



        public IQueryable<T> GetModel(Action<IRepository.Core.IOrderable<T>> orderBy)
        {
            throw new NotImplementedException();
        }

        public IQueryable<T> GetModel(Action<IRepository.Core.IOrderable<T>> orderBy, ISpecification<T> specification)
        {
            throw new NotImplementedException();
        }

        public IQueryable<T> GetModel(Action<IRepository.Core.IOrderable<T>> orderBy, Expression<Func<T, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        public IQueryable<T> GetEntities(ISpecification<T> specification)
        {
            throw new NotImplementedException();
        }

        public IQueryable<T> GetEntities()
        {
            throw new NotImplementedException();
        }

        public IQueryable<T> GetEntities(Expression<Func<T, bool>> predicate)
        {
            throw new NotImplementedException();
        }
    }
}
